package jmine.tec.test.utils.legacy.hibernate;

import java.util.Properties;

import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.context.ThreadLocalSessionContext;

/**
 * Prov� uma SessionFactory para uso com o Hibernate
 * 
 * @author julien
 * @deprecated nao deve ser usado mais.
 */
@Deprecated
public final class HibernateUtils {
    /**
     * 
     */
    private HibernateUtils() {
        super();
    }

    private static volatile SessionFactory factory;

    private static volatile Configuration sharedConfig = new AnnotationConfiguration();

    /**
     * Coloca as propriedades dadas na configuracao
     * 
     * @param props Properties
     * @return {@link Configuration} a configuracao
     */
    public static Configuration configure(final Properties props) {
        return sharedConfig.setProperties(props);
    }

    /**
     * Devolve o {@link Configuration}
     * 
     * @return {@link Configuration}
     */
    public static Configuration getConfiguration() {
        return sharedConfig;
    }

    /**
     * Sets the param
     * 
     * @param driver String param
     * @return the Configuration
     */
    public static Configuration setConnectionDriver(final String driver) {
        return addConfiguration("hibernate.connection.driver_class", driver);
    }

    /**
     * Adiciona um interceptor para todas as sessoes
     * 
     * @param interceptor {@link Interceptor}
     * @return {@link Configuration}
     */
    public static Configuration addInterceptor(final Interceptor interceptor) {
        return getConfiguration().setInterceptor(interceptor);
    }

    /**
     * Sets the param
     * 
     * @param url String param
     * @return the Configuration
     */

    public static Configuration setConnectionUrl(final String url) {
        return addConfiguration("hibernate.connection.url", url);
    }

    /**
     * Sets the param
     * 
     * @param user String param
     * @return the Configuration
     */
    public static Configuration setConnectionUserName(final String user) {
        return addConfiguration("hibernate.connection.username", user);
    }

    /**
     * Sets the param
     * 
     * @param pass String param
     * @return the Configuration
     */
    public static Configuration setConnectionPassword(final String pass) {
        return addConfiguration("hibernate.connection.password", pass);
    }

    /**
     * Sets the param
     * 
     * @param dialect String param
     * @return the Configuration
     */
    public static Configuration setDialect(final String dialect) {
        return addConfiguration("hibernate.dialect", dialect);
    }

    /**
     * Adiciona a propriedade dada
     * 
     * @param key String nome da chave
     * @param value String valor
     * @return {@link Configuration}
     */
    public static Configuration addConfiguration(final String key, final String value) {
        return sharedConfig.setProperty(key, value);
    }

    /**
     * Configura usando o arquivo especificado.
     * 
     * @param resource O caminho para o arquivo
     * @return {@link Configuration}
     */
    public static Configuration configure(final String resource) {
        return sharedConfig.configure(resource);
    }

    /**
     * Retorna a sess�o.
     * 
     * @return Session A Sess�o
     */
    public static Session getSession() {
        return getSessionFactory().getCurrentSession();
    }

    /**
     * Fecha a sess�o.
     */
    public static void closeSession() {
        getSessionFactory().getCurrentSession().close();
    }

    /**
     * Constr�i a SessionFactory se necess�rio.
     * 
     * @return {@link SessionFactory} a session factory
     */
    public static SessionFactory getSessionFactory() {
        if (factory == null) {
            // fixing the current session context class
            sharedConfig.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, ThreadLocalSessionContext.class.getName());
            factory = sharedConfig.buildSessionFactory();
        }
        return factory;
    }

    /**
     * Fecha a SessionFactory.
     */
    public static void closeFactory() {
        if (factory != null) {
            factory.close();
            factory = null;
            sharedConfig = new AnnotationConfiguration();
        }
    }

    /**
     * Executa a operacao dada dentro de uma transacao, efetuando o rollback caso uma excecao seja lancada
     * 
     * @param op a operacao a ser executada
     * @throws Exception caso ocorra uma excecao
     */
    public static void executeWithinTransaction(final SessionOperation op) throws Exception {
        executeWithinTransaction(op, false);
    }

    /**
     * Executa a operacao dada dentro de uma transacao, efetuando o rollback caso uma excecao seja lancada, fechando a sessao se necessario
     * 
     * @param op a operacao a ser executada
     * @param closeSession boolean que indica se a sessao deve ser fechada ao final da operacao
     * @throws Exception caso ocorra uma excecao
     */
    public static void executeWithinTransaction(final SessionOperation op, final boolean closeSession) throws Exception {
        Session s = getSession();
        Transaction tx = s.beginTransaction();
        try {
            op.doOperation(s);
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
            throw e;
        } finally {
            if (closeSession) {
                closeSession();
            }
        }

    }
}
